package com.ziqikeji.simplemvc.system.core;

import com.ziqikeji.simplemvc.system.annotation.Controller;
import com.ziqikeji.simplemvc.system.annotation.Autowired;
import com.ziqikeji.simplemvc.system.annotation.RequestMapping;
import com.ziqikeji.simplemvc.system.dto.ExecutorBean;
import com.ziqikeji.simplemvc.system.dto.Request;
import org.reflections.Reflections;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

/**
 * 主程序
 * 初始化的时候会将所有控制器url和方法对应起来
 * Created by FlyFive on 2018/7/18.
 */
public class Dispatcher {
    public Map<String, ExecutorBean> urlMap = new HashMap<>();

    public Dispatcher(String basePackage){
        Reflections reflections = new Reflections(basePackage);
        Set<Class<?>> classesList = reflections.getTypesAnnotatedWith(Controller.class);

        for(Class clazz : classesList) {
            Object o = null;
            try {
                 o = clazz.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            setObjByFieldAnno(o);
            //定义url
            String url = "/";
            //取到Controller上的RequestMapping值
            if (clazz.isAnnotationPresent(RequestMapping.class)) {
                RequestMapping requestMapping = (RequestMapping) clazz.getAnnotation(RequestMapping.class);
                url += requestMapping.value();
            }

            //得到该类下面的所有方法
            Method[] methods = clazz.getDeclaredMethods();


            for (Method method : methods) {
                //得到该类下面的RequestMapping注解
                RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
                if (null != requestMapping) {
                    ExecutorBean executorBean = new ExecutorBean();
                    executorBean.setObject(o);
                    executorBean.setMethod(method);
                    urlMap.put(url + requestMapping.value(), executorBean);

                }
            }
        }
    }


    public static boolean setObjByFieldAnno(Object o){
        //返回值用于判断是否完成这个方法
        boolean b=false;
        if (null != o) {
            //获取Class
            Class c = o.getClass();
            /*获得域*/
            Field[] fields = c.getDeclaredFields();
            //遍历域
            for (Field f : fields) {
                //将私有化的属性设为true,不然访问不到
                f.setAccessible(true);
                //获取域中的注解，遍历注解
                Annotation[] anns = f.getAnnotations();
                for (Annotation ann : anns) {
                    //这里使用instanceof关键字，判断注解中是否包含MyAutowired
                    if (ann instanceof Autowired) {
                        System.out.println(f.getName() + "--这个域使用了我的注解");
                        //f.getGenericType()：获取该域的类型
                        System.out.println(f.getGenericType().toString() + "--这个域的类型");
                        //转成Class
                        Class c2 = (Class) f.getGenericType();
                        try {//创建实例
                            Object o2 = c2.newInstance();
                            //这个方法是将实例注入到这个域中，详细使用请查阅JAVA API
                            f.set(o, o2);
                            System.out.println("成功注入");
                            //成功则返回true
                            b = true;
                        } catch (InstantiationException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }

                    }

                }
            }
        }
        return b;
    }


    public void init() {
        while(true) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入URL：");
            String url = sc.nextLine();
            Request request = new Request(url);
            this.dispatch(request);
            System.out.println();
        }
    }

    public void dispatch(Request request){
        String url = request.getUrl();
        ExecutorBean bean = urlMap.get(url);
        View view = null;
        try {
            view = (View) bean.getMethod().invoke(bean.getObject());
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        if(view != null) {
            view.show();
        } else {
            System.err.println("该url没有对应的实现");
        }
    }
}
